package ru.rchervot.sanasar.server;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;

import ru.rchervot.sanasar.client.model.AbstractSearchResultsItem;
import ru.rchervot.sanasar.client.model.DefaultQuery;
import ru.rchervot.sanasar.client.model.Query;
import ru.rchervot.sanasar.client.model.filters.FilterItemName;


public abstract class SearchServiceServerAbstract implements SearchServiceServerInternal {
	private static int CACHE_SIZE = 50;
	
	protected static Cache<Integer, ArrayList<Integer>> queryResults = new Cache<Integer, ArrayList<Integer>>(CACHE_SIZE); 
	protected static Cache<Integer, Query> cacheQueries = new Cache<Integer, Query>(CACHE_SIZE);
	protected static Cache<Integer, ArrayList<Integer>> cacheResults = new Cache<Integer, ArrayList<Integer>>(CACHE_SIZE);
	
	public abstract ArrayList loadItems(ArrayList<Integer> itemsIDs, Integer userId) throws Exception;
	public abstract AbstractSearchResultsItem loadItem(int queryID, int userId) throws Exception;
	
	private static final int TEMP_PAGE_SIZE = 5; 
	private static final int TEMP_USER_ID = 133; 
	
	static {
		Query q1 = new DefaultQuery(TEMP_PAGE_SIZE, TEMP_USER_ID);
		q1.setID(1);
		FilterItemName f = new FilterItemName();
		f.setItemNameInclude("aaa");
		q1.addFilter(f);
		cacheQueries.put(1, q1);
		
		Query q2 = new DefaultQuery(TEMP_PAGE_SIZE, TEMP_USER_ID);
		q2.setID(2);
		cacheQueries.put(2, q2);
	}

	public Integer saveQueryToDB(Query q) {
		Integer queryID = new Random().nextInt(1000000);
				
		// save query
		
		return queryID;
	}
	
	public Query loadQueryFromDB(int queryID) {
		// load query
		
		Query q = new DefaultQuery(TEMP_PAGE_SIZE, TEMP_USER_ID);
		q.setID(queryID);
		
		return q;
	}
	
	public ArrayList<Integer> processQuery(Query q) {
		ArrayList<Integer> result = null;
		
		int t = new Random().nextInt(10);
		
		if (t < 5) {
			result = getSome(10);
		} else {
			result = getSome(5000);
		}
		
		cacheResults.put(q.getID(), result);
		
		return result;
	}
	
	private ArrayList<Integer> getSome(int t) {
//		int t = new Random().nextInt(5000);
		ArrayList<Integer> result = new ArrayList<Integer>(t);
		
		// populate result here
		
		for (int i = 0; i < t; i++) {
			result.add(new Random().nextInt(100000));
		}
		
		return result;
	}
	
//	public ArrayList<Integer> processQuery(Query q) throws Exception {
//		ArrayList<Integer> result = new ArrayList<Integer>();
//		
//		String SQLCommand = ServerQueryCandidate.build(q).getSQLCommand();
//		
//		if (SQLCommand == null || SQLCommand.isEmpty()) return result;
//		
//		Context initCtx = new InitialContext();
//		Context envCtx = (Context) initCtx.lookup("java:comp/env");
//		DataSource ds = (DataSource)
//		envCtx.lookup("jdbc/mainDB");
//
//		Connection conn = ds.getConnection();
//		try {
//			Statement stmt = conn.createStatement();
//			try {
//				ResultSet rs = stmt.executeQuery("SELECT id"
//						+ " FROM candidates WHERE deleted = false" +
//						" AND " + SQLCommand +
//						" ORDER BY full_name LIMIT 5000");
//				try {
//					while (rs.next()) {
//						result.add(rs.getInt("id"));
//					}
//				} finally {
//					cleanUp(rs);
//				}
//			} finally {
//				cleanUp(stmt);
//			}
//		} finally {
//			cleanUp(conn);
//		}
//		
//		cacheResults.put(q.getID(), result);
//		
//		return result;
//	}

	protected void cleanUp(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
				conn = null;
			} catch (Exception ex) {
			}
		}
	}
	
	protected void cleanUp(ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
				rs = null;
			} catch (Exception ex) {
			}
		}
	}
	
	protected void cleanUp(Statement st) {
		if (st != null) {
			try {
				st.close();
				st = null;
			} catch (Exception ex) {
			}
		}
	}
	
	public Query getQuery(int queryID) {
		if (queryID == 0) return new DefaultQuery(TEMP_PAGE_SIZE, TEMP_USER_ID);
		
		Query result = cacheQueries.get(queryID);
		
		if (result == null) {
			result = loadQueryFromDB(queryID);
		}
		
		if (result == null) {
			result = new DefaultQuery(TEMP_PAGE_SIZE, TEMP_USER_ID);
		}
		
		return result;
	}
	
	public ArrayList<Integer> getQueryResult(int queryID) throws Exception {
		if (queryID == 0) return new ArrayList<Integer>();
		
		ArrayList<Integer> result = cacheResults.get(queryID);
		
		if (result == null) {
			result = processQuery(getQuery(queryID));
		}
		
		if (result == null) {
			result = new ArrayList<Integer>();
		}
		
		return result;
	}
	
	protected static class Cache<K,V> {
		private final Map<K,V> m;
		
		public Cache(final int size) {
			m = new LinkedHashMap<K,V>(size, .75f, true) {
				
				private static final long serialVersionUID = 1L;

				protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
					return size() > size;
				}
			};
		}
			
		public void put(K arg0, V arg1) {
			m.put(arg0, arg1);
		}
		
		public boolean containsKey(K arg0) {
			return m.containsKey(arg0);
		}
		
		public V get(K arg0) {
			return m.get(arg0);
		}
	}
	
}
